package pt.utl.ist.isr.livetrack.tracker;

import pt.utl.ist.isr.livetrack.server.impl.ZoneImpl;
import pt.utl.ist.isr.livetrack.server.impl.PerimeterImpl;
import eu.anorien.mhl.Fact;
import eu.anorien.mhl.Hypothesis;
import eu.anorien.mhl.Watcher;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JFrame;
import org.apache.log4j.Logger;
import pt.utl.ist.isr.livetrack.server.interfaces.Zone;
import pt.utl.ist.isr.livetrack.tracker.gui.BestHyp;
import pt.utl.ist.isr.livetrack.tracker.mht.EntityInFact;
import pt.utl.ist.isr.livetrack.tracker.mht.TDetection;
import pt.utl.ist.isr.livetrack.tracker.mht.MHTracker;

/**
 *
 * @author David Miguel Antunes <davidmiguel [ at ] antunes.net>
 */
public class MCT {

    private static final Logger logger = Logger.getLogger(MCT.class);
    private PerimeterImpl perimeter;
    private MHTracker tracker;

    public MCT(
            String[] cameraNames,
            int[][] connectionMatrix,
            int maxNumLeaves,
            int maxDepth,
            int timeUndetected,
            int bestK,
            double probUndetected,
            double probNewTarget,
            double probFalseAlarm,
            double probChangeZone,
            int gateSize,
            double newHistogramWeigth,
            int histogramDifferencePenalization,
            boolean bestHypOutput) {

        logger.info("Version: 1.07");

        this.tracker = new MHTracker(maxNumLeaves, maxDepth, timeUndetected, bestK, probUndetected, probNewTarget, probFalseAlarm, probChangeZone, gateSize, newHistogramWeigth, histogramDifferencePenalization, bestHypOutput);
        this.perimeter = new PerimeterImpl();

        if (bestHypOutput) {
            tracker.getLeafVisualizer().setVisible(true);
            tracker.getClusterVisualizer().setVisible(true);
        }

        Map<String, Zone> zones = perimeter.getZonesLocal();

        for (int i = 0; i < cameraNames.length; i++) {
            String name = cameraNames[i];
            zones.put(name, new ZoneImpl(name, "camera" + name));
            perimeter.getCamZoneMap().put(Long.parseLong(name), zones.get(name).getId());
        }

        String s = "";
        for (int i = 0; i < connectionMatrix.length; i++) {
            for (int j = 0; j < connectionMatrix[0].length; j++) {
                int isConnected = connectionMatrix[i][j];
                if (isConnected != 0) {
                    s += ("Camera " + cameraNames[i] + " connects to " + cameraNames[j]) + "\n";
                    zones.get(cameraNames[i]).getConnections().add(zones.get(cameraNames[j]).getId());
                }
            }
        }
        logger.debug(s);

        if (bestHypOutput) {
            BestHyp bestHyp = new BestHyp(tracker);
            JFrame frame = new JFrame("Best hypothesis");
            frame.setSize(600, 600);
            frame.add(bestHyp);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        }
    }

    public void newScan(long currentTime, List<Detection> detections) {
        logger.debug("==New Scan==");
        List<TDetection> tDetections = new ArrayList<TDetection>();
        for (Detection detection : detections) {
            tDetections.add(new TDetection<BufferedImage>(
                    detection.getUpperBodyHistogram(),
                    detection.getImage(),
                    perimeter.getZonesLocal().get(perimeter.getCamZoneMapLocal().get((long) detection.getCamId()))));
        }
        String s = ("Detections:");
        for (TDetection tDetection : tDetections) {
            s += ("\t" + tDetection) + "\n";
        }
        logger.debug(s);
        tracker.newScan(currentTime, tDetections);
        showBestHyp();
    }
    private long time = 0;

    public void newScan(List<Detection> detections) {
        newScan(time++, detections);
    }

    public Hypothesis getBestHypothesis() {
        return tracker.getBestHypothesis();
    }

    public void registerWatcher(Watcher watcher) {
        tracker.registerWatcher(watcher);
    }

    public Map<Long, List<Long>> getBestHyp() {
        Hypothesis h = tracker.getBestHypothesis();
        Map<Long, List<Long>> map = new HashMap<Long, List<Long>>();
        for (Long id : perimeter.getCamZoneMap().keySet()) {
            map.put(id, new ArrayList<Long>());
        }
        for (Fact f : h.getFacts().keySet()) {
            EntityInFact fact = (EntityInFact) f;
            map.get(Long.parseLong(fact.getZone().getId())).add(fact.getEntity().getId());
        }
        return map;
    }

    private void showBestHyp() {
        String s = ("==Best Hyp==");
        for (Fact f : tracker.getBestHypothesis().getFacts().keySet()) {
            EntityInFact fact = (EntityInFact) f;
            s += ("\t" + fact.getEntity() + " is in " + fact.getZone() + " last detected at " + fact.getLastDetection()) + "\n";
        }
        logger.debug(s);
    }
}
